package com.ruoyi.common.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.DesCipherUtil;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;

@WebFilter(urlPatterns = "/*", filterName = "channelFilter")
// 通过自定义过滤器,将流继续保存下去 https://www.codenong.com/cs107098749/
public class ChannelFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(ChannelFilter.class);

    // 项目启动初始化的时候会被加载。
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    // 过滤请求，预处理。
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;

        ResponseWrapper responseWrapper = null;

        String desnet = httpServletRequest.getHeader("Desnet"); // 是否需要加密
        String afterparams = ""; // 将参数放入重写的方法中
        Object aesparams = null;
        // 判断需要解密 且 post请求 且 body有值
        if (StringUtils.isNotEmpty(desnet)) {
            if ("POST".equals(httpServletRequest.getMethod().toUpperCase())) {
                String allparams = getBody(httpServletRequest); // 请求body
                // 获取httpServletRequest的body参数
                if (StringUtils.isNotEmpty(allparams)) {
                    try {
                        Map<String, Object> allparamsMap = JSONObject.parseObject(allparams);
                        aesparams = allparamsMap.get("params");
                        if (aesparams != null) {
                            String desparams = "";
                            try {
                                desparams = DesCipherUtil.aesDecrypt(aesparams.toString());
                            } catch (Exception e) {
                                throw new RuntimeException("解密出错！");
                            }
                            JSONObject jsStr = JSONObject.parseObject(desparams);
                            afterparams = jsStr.toJSONString();
                        }
                    } catch (Exception e) {
                        throw new RuntimeException("数据解密出错！");
                    }
                }
            }
            // 执行将参数放入重写的方法中
            httpServletRequest = new RequestWrapper(httpServletRequest, afterparams);
            responseWrapper = new ResponseWrapper(httpServletResponse);
            filterChain.doFilter(httpServletRequest, responseWrapper); // 执行过滤

            String encryptStr = "";
            // 判断是否有值
            if (responseWrapper != null) {
                byte[] contentByte = responseWrapper.getContent(); // 获取返回值
                // 返回值有值
                if (contentByte.length > 0) {
                    String result = new String(contentByte, "UTF-8");
                    logger.info(
                            httpServletRequest.getRequestURL() + "===> return origin data ===> "
                                    + JSON.toJSONString(result));
                    try {
                        encryptStr = DesCipherUtil.aesEncrypt(result); // 加密
                        logger.info("<=== 分割线 ===> ");
                        logger.info(httpServletRequest.getRequestURL() + "===> return aesEncrypt data ===> "
                                + JSON.toJSONString(encryptStr));
                    } catch (Exception e) {
                        throw new RuntimeException("加密出错！");
                    }
                }
            }
            // 把返回值输出到客户端 这里用的 servletResponse，比较特殊
            ServletOutputStream out = servletResponse.getOutputStream();
            out.write(encryptStr.getBytes());
            out.flush();
        } else {
            filterChain.doFilter(httpServletRequest, httpServletResponse); // 执行过滤
        }
    }

    // 获取Request的body数据
    private String getBody(ServletRequest request) {
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {

        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return stringBuilder.toString();
    }

    // 项目停止前，会执行该方法。
    @Override
    public void destroy() {

    }
}